home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
zoom.c
< prev
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
484 lines
/*
* $Id: zoom.c,v 0.91 1994/02/20 00:53:21 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Purpose:
* Magnify a region of the image to the window/screen size.
*
* Limitations:
* Only integer zoom factors supported. Could be easily lifted
* if there is any request.
*
*/
#if !defined(lint) && defined(F_ID)
char *id_zoom = "$Id: zoom.c,v 0.91 1994/02/20 00:53:21 zhao Pre-Release $";
#endif
#include "bit.h"
#include "extern.h"
#include <math.h>
/******************** Limits ******************************/
#define DEF_ZOOM 3.0 /* default zoom factors */
#define MIN_ZOOM 2.0 /* minimum factor */
#define MAX_ZOOM 10.0 /* maximum factor */
/********************* local variables *********************/
static int zx, zy, dx, dy; /* zoom region */
static int fr_col = 1; /* frame color */
static float zoomx, zoomy, z0; /* zoom factors */
static float maxzx, maxzy; /* maximum zoom factors */
static int zsmooth; /* smooth zooming. Undocumented */
/********************** local functions **********************/
static int zoom_init(IPTR, int);/* initialize */
static int zoom_popup(IPTR); /* handle pop-up */
static int zoom_kbd(IPTR, int); /* handle keyboard */
static void zoom_mouse(IPTR, long); /* mouse event handler */
static int zooming(IPTR); /* yep, do it */
/****************************************************************
* Global entry point
****************************************************************/
int
image_zoom(IPTR im)
{
int done = 0;
short val = 0;
long dev;
if (!image_ready(im, "Zoom"))
return -1;
deactivate_all_forms();
zoom_init(im, 0);
/* what to do if window resizes */
install_wm_handler(zoom_init);
/* force rectangluar region */
set_rubber_obj(RB_RECT);
/* looping until ESC or popup entry done is selected */
do
{
dev = rubber_cursor(win_id, &val, &zx, &zy, dx, dy, fr_col);
switch (bit_handle_event(dev, val))
{
case MENUBUTTON:
done = val && zoom_popup(im);
break;
case KEYBD:
done = zoom_kbd(im, val);
break;
case ESCKEY:
done = (val > 0);
break;
case LEFTMOUSE:
case MIDDLEMOUSE:
if (val)
zoom_mouse(im, dev);
break;
}
}
while (!done);
/* clean up */
rubber_finish();
rectzoom(1.0, 1.0);
fl_activate_all_forms();
remove_wm_handler(zoom_init);
return 0;
}
/**********************************************************
* Show current zoom factos in InfoPanel
*********************************************************/
static void
show_zoom_factor(void)
{
char rep[30];
sprintf(rep, "Zx=%.0f Zy=%.0f", zoomx, zoomy);
show_misc_info(rep);
}
/***********************************************************
* Make sure the setup is valid:
* In single buffer mode, zoom region may not be outside image
************************************************************/
static void
check_and_adjust(IPTR im)
{
/* zoom must be within min & max */
if (zoomx < MIN_ZOOM)
zoomx = MIN_ZOOM;
else if (zoomx > maxzx)
zoomx = maxzx;
if (zoomy < MIN_ZOOM)
zoomy = MIN_ZOOM;
else if (zoomy > maxzy)
zoomy = maxzy;
dx = (win_w - 1) / zoomx;
dy = (win_h - 1) / zoomy;
if (!double_buf)
{
if (dx >= im->w)
dx = im->w - 1;
if (dy >= im->h)
dy = im->h - 1;
/* zoom region must be inside of image */
if (zx < im->xi)
zx = im->xi;
if (zy < im->yi)
zy = im->yi;
if (zx + dx - 1 > im->xf)
zx = im->xf - dx + 1;
if (zy + dy - 1 > im->yf)
zy = im->yf - dy + 1;
}
/* show the possibly adjusted zoom factors */
show_zoom_factor();
}
/******************************************************************
* Initialization
******************************************************************/
/* ARGSUSED */
static int
zoom_init(IPTR im, int wme)
{
int rect_minx = 40, rect_miny = 40;
/* default zoom factor magnifies image to full screen */
zoomx = (win_w - 1) / im->w;
zoomy = (win_h - 1) / im->h;
/* default to uniform zooming */
zoomx = zoomy = Min(zoomx, zoomy);
if (zoomx < DEF_ZOOM)
zoomx = zoomy = DEF_ZOOM;
/* zoom factors that can safely be used */
z0 = zoomx;
/* adjust the minimum region for small images */
if (rect_minx > im->w / 2)
rect_minx = im->w / 2;
if (rect_miny > im->h / 2)
rect_miny = im->h / 2;
/* maximum zoom factors that can be used */
maxzx = ((float) win_w - 5.0) / rect_minx + 0.1;
maxzy = ((float) win_h - 5.0) / rect_miny + 0.1;
/* truncate to integer */
maxzx = (float) ((int) maxzx);
maxzy = (float) ((int) maxzy);
if (maxzx > MAX_ZOOM)
maxzx = MAX_ZOOM;
if (maxzy > MAX_ZOOM)
maxzy = MAX_ZOOM;
check_and_adjust(im);
/*
* there is no point in restricting zoom region in double buffer mode as
* we simply do a rectcopy
*/
set_rubber_bounds(!double_buf, im->xi, im->yi, im->w, im->h);
set_rubber_center(1);
return 0;
}
/***************************************************************
* Handle zooming by leftmouse or middlemouse
************************************************************/
static void
zoom_mouse(IPTR im, long dev)
{
if (control_down)
{
if (dev == LEFTMOUSE)
{
zoomx += 1.0;
zoomy += 1.0;
}
else
{
zoomx -= 1.0;
zoomy -= 1.0;
}
check_and_adjust(im);
}
else
zooming(im);
}
/*******************************************************************
* Handle zoom popup menu
* return 1 if finsihing else zero
*****************************************************************/
static int
zoom_popup(IPTR im)
{
int ret, c;
static long zoom_menu = -1;
if (zoom_menu < 0)
zoom_menu = defpup("Zoom%t|Help|BColor|2x2|3x3|4x4|5x5|"
"Return %x100");
ret = 0;
switch ((c = dopup(zoom_menu)))
{
case 1:
help_cb(0, HELP_ZOOM);
break;
case 2:
++fr_col;
fr_col %= over_pup_colors;
rubber_show(fr_col);
break;
case 3:
case 4:
case 5:
case 6:
zoomx = zoomy = (c - 1);
break;
case 7:
zsmooth = !zsmooth;
break;
case 100:
ret = 1;
break;
}
check_and_adjust(im);
return ret;
}
/*******************************************************************
* Handle all keyboard events. Return 1 if ESC else 0
******************************************************************/
static int
zoom_kbd(IPTR im, int val)
{
int ret = 0;
switch (val)
{
case 'x':
zoomx += 1.0;
break;
case 'X':
zoomx -= 1.0;
break;
case 'y':
zoomy += 1.0;
break;
case 'Y':
zoomy -= 1.0;
break;
case '0':
zoomx = zoomy = z0;
break;
case 27:
ret = 1;
break;
default:
break;
}
check_and_adjust(im);
return ret;
}
static int newx, newy;
static int xd, yd;
/****************************************************************
* Magnify the requested region (zx, zy, dx, dy) in double buffer
* mode.
****************************************************************/
/* ARGSUSED */
static int
dbl_zoom_it(IPTR im)
{
rectcopy(zx, zy, zx + dx - 1, zy + dy - 1, xd, yd);
return 0;
}
/********************************************************************
* Magnify in single buffer mode: We get a piece of image from the
* image matrix and use hardwar zoom to show it
*******************************************************************/
static int
sgl_zoom_it(IPTR im)
{
void **aa;
set_current_window(win_id);
reshapeviewport();
if (!zsmooth) /* pixel replication */
{
rectzoom(zoomx, zoomy);
if ((aa = get_subimage(im, zx, zy, dx, dy)))
{
Rectwrite(xd, yd, xd + dx - 1, yd + dy - 1, aa[0]);
free_mat(aa);
}
}
else
{
/* linear interpolation. Undocumented */
IPTR zim = get_mem_imgptr();
memcpy(zim, im, sizeof(*im));
zim->ok = 0;
zim->mraster = zim->raster = 0;
rectzoom(1.0, 1.0);
aa = get_subimage(im, zx, zy, dx, dy);
if (fill_image_struct(zim, aa, dy, dx, im->type) < 0)
return -1;
/*
* scale it. The third parameter is the subpixel sampling
* parameter: 1--simple blening, 2-- box filter
*/
img_scale(zim, newy, newx, 1, 0, 0);
display_image(zim, 0, 0);
free_image(zim);
}
return 0;
}
/**********************************************************************
* Continuously zooming as long as mouse button is down
*********************************************************************/
static int
zooming(IPTR im)
{
int ozx = 0, ozy = 0;
int oreport = report_level; /* save old settings */
int (*zoom_it) (IPTR);
rubber_hide();
zoom_it = (double_buf ? dbl_zoom_it : sgl_zoom_it);
/* shut up reporting */
report_level = -1;
/* zoomed size */
newx = dx * zoomx;
newy = dy * zoomy;
/* lower left corner in window */
xd = (win_w - newx) / 2;
yd = (win_h - newy) / 2;
if (!double_buf)
{
/* we can get away with rectcopy for first time only */
if (!zsmooth)
{
set_current_window(win_id);
reshapeviewport();
rectzoom(zoomx, zoomy);
rectcopy(zx, zy, dx + zx - 1, dy + zy - 1, xd, yd);
}
else
{
zoom_it(im);
}
WHERE_R2W(zx, zy, win_xo, win_yo);
ozx = zx - dx / 2;
ozy = zy - dy / 2;
}
else
{
rectzoom(zoomx, zoomy);
frontbuffer(1);
backbuffer(0);
}
/* zooming while mouse is down */
do
{
WHERE_R2W(zx, zy, win_xo, win_yo);
zx -= dx / 2;
zy -= dy / 2;
if (zx != ozx || zy != ozy)
{
ozx = zx;
ozy = zy;
check_and_adjust(im);
show_rect_ori(zx, zy);
zoom_it(im);
}
}
while (mouse_down);
#ifndef SGL_BUF
if (double_buf)
{
frontbuffer(0);
backbuffer(1);
}
#endif
/* clean up */
rectzoom(1.0, 1.0);
im->io->display(im, 0, 1);
rubber_moveto(&zx, &zy, &dx, &dy);
report_level = oreport;
return 0;
}